////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Filename:    FruitFrenzyGuts.h                                            //
//  Developer:   Tommy Riddle                                                 //
//  Create date: 03/18/2005                                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Description: This is the class declaration for the slot gut of the        //
//               Australian Slot machine called Fruit Frenzy.                 //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//        Copyright (c) 2005 - Realtime Gaming.  All rights reserved.         //
////////////////////////////////////////////////////////////////////////////////

#if !defined(__FRUITFRENZYGUTS_H__)
#define __FRUITFRENZYGUTS_H__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "slotguts.h"
#include "getrand.h"

class FruitFrenzyGuts : public SlotGuts
{
public:
	FruitFrenzyGuts();

	virtual ~FruitFrenzyGuts();

private:
	// Shared enums between client and server
	#include "FruitFrenzyCommon.h"

	// Helpful lookup arrays.
	static SpinResult m_aLineWinSpinResults[][6];

	static SpinResult m_aScatterWinSpinResults[][6];

	static int8 m_aPayLineOffsets[25][5];

	// Inline functions to use with the arrays that also do
	// bounds checking.
	static SpinResult lookupLineWinSpinResult( uint8 nIconType, uint8 nCount )
	{
		if ( nIconType < NUM_VALID_ICONS && nCount < 6 )
		{
			return m_aLineWinSpinResults[ nIconType ][ nCount ];
		}

		ASSERT( false );
		return EVT_INVALID;
	}

	static SpinResult lookupScatterWinSpinResult( uint8 nIconType, uint8 nCount )
	{
		if ( nIconType < NUM_VALID_ICONS && nCount < 6 )
		{
			return m_aScatterWinSpinResults[ nIconType ][ nCount ];
		}

		ASSERT( false );
		return EVT_INVALID;
	}

	static int32 getPaylineScatterPosition( uint8 Payline )
	{
		int32 nPosition = 0;

		for ( int n = 0; n < 5; n++ )
		{
			int32 nShift = m_aPayLineOffsets[ Payline ][ n ] - 1;

			nShift *= -5;
				
			nPosition |= ( 1 << ( nShift + n ) );
		}

		return nPosition;
	}

	// Helper functions for classifyStops.
	SpinResult getPineappleLineWinResult( uint8* stops ) const;

	SpinResult getLineWinResultWithPossibleSubstitution( uint8* stops, uint8 line, uint8 testIcon, bool& bSubstitution );

	bool doesPineappleLineWinPayMore( SpinResult srPineapple, SpinResult srOther ) const;

	// Helper functions for classifyScatters.
	void tryForJackpot( SlotSpin* spin );

	SpinResult getScatterWinResult( SlotSpin* spin, uint8 testIcon, int32& scatterPositions ) const;
	
	void evaluateScatterWin( SlotSpin* spin, SpinResult srScatterResult, int32 scatterPositions );

	void addDaredevilStrawberryScatters( SlotSpin* spin );

	enum PaylineFeatureTrigger
	{
		pftNone,
		pftNearMiss,
		pftFeatureTriggered
	};

	PaylineFeatureTrigger getPaylineFeatureTrigger( uint8 nPayline );
	void setPaylineFeatureTrigger( uint8 nPayline, PaylineFeatureTrigger ePaylineResult );

	int32 getNumFeatureRounds();
	void initializeNumFeatureRounds();
	void incrementNumFeatureRounds();

	int32 getCurrentFeatureRound();
	void initializeCurrentFeatureRound();
	void incrementCurrentFeatureRound();

	int32 getTotalPointsForRound();
	void initializeTotalPointsForRound();

	int32 getCurrentShotsRemaining();
	void initializeCurrentShotsRemaining();
	void decrementCurrentShotsRemaining();

	int32 getCurrentPoints();
	void initializeCurrentPoints();
	void incrementCurrentPoints();

	bool getLastShotHit();
	void setLastShotHit( bool bLastShotHit );

protected:
	virtual int32 getNumLinesBet();

public:
	virtual void classifyStops( SpinLine* spinline, uint8* stops, uint8 bet, uint8 line,
		uint8& rtnresult, uint8& multiplier );

	virtual void classifyScatters( SlotSpin *spin );

    virtual bool8 isValidGuts();

    virtual void getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier, uint8& nNoteId );

	virtual bool8 processClientData( uint8 bonusGameType, int32 bonusDataCount, int32 *bonusData );

protected:
	// Override these framework functions.
	virtual void preSpinClassifyResults( SlotSpin* spin );
    virtual void postSpinClassifyResults( SlotSpin* spin );

	virtual bool8 hasSavedGames();

	virtual void Debug_SetLoserStops( uint8* pStops );

	virtual void initDebugFunctionMap();

	enum
	{
		EVT_DEBUG_FUNCTION_WIN_RANDOM = BEGIN_SUB_MODIFY_NEXT_RESULT_FUNCTION_RANGE,
		EVT_DEBUG_FUNCTION_WIN_ZERO,
		EVT_DEBUG_FUNCTION_WIN_ONE,
		EVT_DEBUG_FUNCTION_WIN_TWO,
		EVT_DEBUG_FUNCTION_WIN_THREE,

		EVT_DEBUG_FUNCTION_HIT_FIRST,
		EVT_DEBUG_FUNCTION_HIT_SECOND,
		EVT_DEBUG_FUNCTION_HIT_THIRD,
	};

	void DebugFeature_WinRandom(SlotSpin *spin );
	void DebugFeature_WinZero(SlotSpin *spin );
	void DebugFeature_WinOne(SlotSpin *spin );
	void DebugFeature_WinTwo(SlotSpin *spin );
	void DebugFeature_WinThree(SlotSpin *spin );

	void DebugFeature_HitFirst( SlotSpin *spin );
	void DebugFeature_HitSecond( SlotSpin *spin );
	void DebugFeature_HitThird( SlotSpin *spin );

    static int g_nFeatureWins;
    static int g_nWinSequence;

    //Bit mask specifying in which order the shots should win in the feature game
    enum Debug_FeatureWinSequence
    {
        fwsNone = 0x000,
        fwsFirst = 0x001,
        fwsSecond = 0x010,
        fwsThird = 0x100,
    };

    //Should this feature shot win?
    void Debug_isWinningShot(bool&);
};  


#endif // !defined(__FRUITFRENZYGUTS_H__)
